package org.easymodelers.gmf.creator.impl;

import java.io.IOException;

import org.easymodelers.gmf.creator.GmfGraphCreator;
import org.easymodelers.gmf.utils.GmfModelsUtils;
import org.easymodelers.gmf.utils.ModelCreatorCallback;
import org.easymodelers.modeler.data.Element;
import org.easymodelers.modeler.data.ElementLabel;
import org.easymodelers.modeler.data.Modeler;
import org.eclipse.gmf.gmfgraph.Canvas;
import org.eclipse.gmf.gmfgraph.ChildAccess;
import org.eclipse.gmf.gmfgraph.DiagramLabel;
import org.eclipse.gmf.gmfgraph.FigureDescriptor;
import org.eclipse.gmf.gmfgraph.FigureGallery;
import org.eclipse.gmf.gmfgraph.GMFGraphFactory;
import org.eclipse.gmf.gmfgraph.Label;
import org.eclipse.gmf.gmfgraph.Node;
import org.eclipse.gmf.gmfgraph.Rectangle;
import org.eclipse.gmf.gmfgraph.Shape;

public class DefaultGmfGraphCreator implements GmfGraphCreator {

	private GMFGraphFactory getGraphFactory() {
		return GMFGraphFactory.eINSTANCE;
	}
	
	public void createGmfGraph(String modelPath, final Modeler modeler) throws IOException {
		GmfModelsUtils.createGmfModel(modelPath, new ModelCreatorCallback<Canvas>() {
			public Canvas createModelRootElement() throws IOException {
				GMFGraphFactory graphFactory = getGraphFactory();
				Canvas canvas = graphFactory.createCanvas();
				FigureGallery figureGalery = graphFactory.createFigureGallery();
				canvas.getFigures().add(figureGalery);

				for (Element element : modeler.getElements()) {
					handleElement(element, canvas, figureGalery);
				}
				
				return canvas;
			}
		});
	}

	private Shape createShapeForElement(
					GMFGraphFactory graphFactory, Element element) {
		String shapeType = element.getShape();
		if (shapeType==null) {
			shapeType = "rectangle";
		}
		shapeType = shapeType.toLowerCase();

		if ("rectangle".equals(shapeType)) {
			return graphFactory.createRectangle();
		} else if ("roundedrectangle".equals(shapeType)) {
			return graphFactory.createRoundedRectangle();
		} else if ("ellipse".equals(shapeType)) {
			return graphFactory.createEllipse();
		} else {
			return graphFactory.createRectangle();
		}
	}

	private void handleElement(Element element, Canvas canvas, FigureGallery figureGalery) {
		GMFGraphFactory graphFactory = getGraphFactory();

		FigureDescriptor elementFigureDescriptor = graphFactory.createFigureDescriptor();
		elementFigureDescriptor.setName(element.getName() + "FigureDescriptor");
		figureGalery.getDescriptors().add(elementFigureDescriptor);
		
		Shape elementShape = createShapeForElement(graphFactory, element);
		elementShape.setName(element.getName() + "Figure");
		elementFigureDescriptor.setActualFigure(elementShape);

		ElementLabel elementLabel = element.getLabel();
		ChildAccess labelChildAccess = null;
		if (elementLabel!=null) {
			Label label = graphFactory.createLabel();
			label.setName(elementLabel.getName() + "Label");
			elementShape.getChildren().add(label);
			
			labelChildAccess = graphFactory.createChildAccess();
			labelChildAccess.setFigure(label);
			String accessorName = "getFigure"
								+ label.getName().substring(0, 1).toUpperCase()
								+ label.getName().substring(1);
			labelChildAccess.setAccessor(accessorName);
			elementFigureDescriptor.getAccessors().add(labelChildAccess);
		}
		
		Node elementNode = graphFactory.createNode();
		elementNode.setName(element.getName()+"Node");
		elementNode.setFigure(elementFigureDescriptor);
		canvas.getNodes().add(elementNode);

		if (elementLabel!=null) {
			DiagramLabel labelDiagramLabel = graphFactory.createDiagramLabel();
			labelDiagramLabel.setName(elementLabel.getName()+"DiagramLabel");
			labelDiagramLabel.setFigure(elementFigureDescriptor);
			labelDiagramLabel.setAccessor(labelChildAccess);
			canvas.getNodes().add(labelDiagramLabel);
		}
	}
}
